import { AudioClip, AudioSource, Node } from "cc";
import { AudioId } from "../../game/config/Config";
import { Audiocfg } from "../config/Appcfg";
import { CacheUtils } from "../utils/CacheUtils";
import { LogMgr } from "./LogMgr";
import { ResourceMgr } from "./ResourceMgr";

export class AudioMgr {
    private static instance: AudioMgr;
    private audioNode: Node;
    private constructor() { }
    public static getInstance(): AudioMgr {
        if (this.instance == null) {
            this.instance = new AudioMgr();
            this.instance.audioNode = new Node()
        }
        return this.instance;
    }
    private audioSourceMap: Map<string, AudioSource> = new Map();
    private audioClipMap: Map<string, AudioClip> = new Map();
    private EffectAduioSource: AudioSource
    private EffectAduioSource1: AudioSource
    /** UI配置 */
    private ADConf: { [key: string]: Audiocfg } = {};
    private otherADConf: { [key: string]: Audiocfg }[] = [];
    private musicKeys: string[] = []

    public init(cnf: { [key: string]: Audiocfg }) {
        this.ADConf = cnf
    }
    public loadAudio(audId: AudioId, callback: Function) {
        let cfg = this.getAdConf(audId)
        if (!cfg) {
            LogMgr.getInstance().ogError("音效没有配置：", audId)
            return;
        }
        ResourceMgr.getInstance().loadRes(cfg.bundle, cfg.path, AudioClip, (res: AudioClip) => {
            this.audioClipMap.set(cfg.path, res)
            if (callback) {
                callback();
            }
        })
    }
    public addAdConf(conf: { [key: string]: Audiocfg }) {
        this.otherADConf.push(conf)
    }
    public getAdConf(uid: any): Audiocfg {
        let conf = this.ADConf[uid]
        if (conf) {
            return conf;
        }
        for (let i = 0; i < this.otherADConf.length; i++) {
            let conf = this.otherADConf[i]
            let c = conf[uid]
            if (c) {
                return c;
            }
        }
        return null;
    }
    /**
     * 创建一个AudioSource
     * @param name audioSource的名字
     */
    public creatreAudioSource(name: string): AudioSource {
        let audioEngine: AudioSource = this.audioNode.addComponent(AudioSource)
        if (this.audioSourceMap.has(name)) {
            //已经存在了 以前的销毁
            this.audioSourceMap.get(name).destroy();
        }
        this.audioSourceMap.set(name, audioEngine)
        return audioEngine;
    }
    /**
     * 获取一个AudioSource 没有的话自动创建
     * @param name audioSource的名字
     */
    public getAudioSource(name: string): AudioSource {
        if (this.audioSourceMap.has(name)) {
            return this.audioSourceMap.get(name)
        }
        return this.creatreAudioSource(name)
    }
    /**播放一个背景音乐 */
    public playMusic(audio: AudioId, audioSourceName: string, loop: boolean = true, volume: number = 1) {
        if (CacheUtils.canPlayMusin()) {
            let audioSource = this.getAudioSource(audioSourceName)
            if (audioSource == null) {
                LogMgr.getInstance().ogError("audioSourceName：" + audioSourceName + "不存在")
                return;
            }
            //默认关闭前面的
            audioSource.stop();
            let cfg = this.getAdConf(audio)
            if (cfg == null) {
                LogMgr.getInstance().ogError("audio id:" + audio + "不存在")
                return;
            }
            if (loop) {
                this.addMusicKey(audioSourceName)
            }
            let ishas = this.audioClipMap.has(cfg.path)
            if (ishas) {
                let clip = this.audioClipMap.get(cfg.path)
                audioSource.clip = clip;
                audioSource.loop = loop;
                audioSource.volume = volume
                audioSource.play()
            } else {
                ResourceMgr.getInstance().loadRes(cfg.bundle, cfg.path, AudioClip, (res: AudioClip) => {
                    audioSource.clip = res;
                    this.audioClipMap.set(cfg.path, res)
                    audioSource.loop = loop;
                    audioSource.volume = volume
                    audioSource.play()
                })
            }
        }
    }
    private addMusicKey(key: string) {
        for (let i = 0; i < this.musicKeys.length; i++) {
            let mkey = this.musicKeys[i]
            if (mkey == key) {
                return false;
            }
        }
        this.musicKeys.push(key)
        return true;
    }
    /**删除一个music */
    private removeMusicKey(key: string) {
        for (let i = 0; i < this.musicKeys.length; i++) {
            let mkey = this.musicKeys[i]
            if (mkey == key) {
                this.musicKeys.splice(i, 1)
                return true;
            }
        }
        return false
    }
    /**恢复所有的音乐播放 */
    public resumeAllMusic() {
        this.musicKeys.forEach((audiokey: string) => {
            this.resumeMusic(audiokey)
        })
    }
    /**暂停所有正在播放的音乐 不包含音效 */
    public pauseAllMusic() {
        this.musicKeys.forEach((audiokey: string) => {
            this.pauseMusic(audiokey)
        })
    }
    /**暂停一个音乐 */
    public pauseMusic(audioSourceName: string) {
        let audioSource = this.getAudioSource(audioSourceName)
        if (audioSource == null) {
            LogMgr.getInstance().ogError("audioSourceName：" + audioSourceName + "不存在")
            return;
        }
        audioSource.pause();
    }
    /**恢复一个音乐 */
    public resumeMusic(audioSourceName: string) {
        let audioSource = this.getAudioSource(audioSourceName)
        if (audioSource == null) {
            LogMgr.getInstance().ogError("audioSourceName：" + audioSourceName + "不存在")
            return;
        }
        audioSource.play();
    }

    /**关闭一个音乐 */
    public stopMusic(audioSourceName: string) {
        let audioSource = this.getAudioSource(audioSourceName)
        if (audioSource == null) {
            LogMgr.getInstance().ogError("audioSourceName：" + audioSourceName + "不存在")
            return;
        }
        this.removeMusicKey(audioSourceName)
        audioSource.stop();
    }
    /**关闭所有的音乐 */
    public stopAll() {
        this.audioSourceMap.forEach((audioSource: AudioSource, name: string) => {
            audioSource.stop();
        })
    }
    /**播放一个音效 */
    public playEffect(audioId: AudioId, volume = 1) {

        if (CacheUtils.canPlayEffect()) {
            let audioSource = this.EffectAduioSource;
            if (audioSource == null) {
                //创建一个
                audioSource = this.getAudioSource("effect")
            }
           
            let cfg = this.getAdConf(audioId)
            let ishas = this.audioClipMap.has(cfg.path)
           
            if (ishas) {
                let clip = this.audioClipMap.get(cfg.path)
                // audioSource.clip = clip;
                // audioSource.volume = volume;
                // audioSource.play()
                //这个音频播放听说会导致内存卡爆问题，如果后续有反馈的话在修改 3.8解决了内存泄漏问题 https://forum.cocos.org/t/topic/147670/6
                audioSource.playOneShot(clip, volume);
            } else {
                ResourceMgr.getInstance().loadRes(cfg.bundle, cfg.path, AudioClip, (res: AudioClip) => {
                    this.audioClipMap.set(cfg.path, res)
                    // audioSource.clip = res;
                    // audioSource.volume = volume;
                    // audioSource.play()
                    //这个音频播放听说会导致内存卡爆问题，如果后续有反馈的话在修改
                    audioSource.playOneShot(res, volume);
                })
            }
        }
    }



    
    /**播放一个音效 */
    public playEffectByPath(path: string, audioSourceName: string, volume: number = 1, isLoop = false) {
        if (CacheUtils.canPlayEffect()) {
            let audioSource = this.EffectAduioSource
            if (audioSource == null) {
                //创建一个
                audioSource = this.getAudioSource(audioSourceName)
            }
            let ishas = this.audioClipMap.has(path)
            if (ishas) {
                let clip = this.audioClipMap.get(path)
                audioSource.clip = clip;
                audioSource.volume = volume;
                audioSource.loop = isLoop;
                audioSource.play()
            } else {
                ResourceMgr.getInstance().loadRes("audio", path, AudioClip, (res: AudioClip) => {
                    this.audioClipMap.set(path, res)
                    audioSource.clip = res;
                    audioSource.volume = volume;
                    audioSource.loop = isLoop;
                    audioSource.play()
                })
            }
        }
    }
    /**
  * 播放语音
  * @param path 
  * @param audioSourceName 
  * @returns 
  */
    public playAudioFromPath(bundle: string, path: string, audioSourceName: string, loop?: boolean, callback?: Function) {
        if (CacheUtils.canPlayMusin()) {
            let audioSource = this.getAudioSource(audioSourceName)
            if (audioSource == null) {
                LogMgr.getInstance().ogError("audioSourceName：" + audioSourceName + "不存在")
                return;
            }
            //默认关闭前面的
            audioSource.stop();
            let ishas = this.audioClipMap.has(path)
            if (loop) {
                this.addMusicKey(audioSourceName)
            }
            if (ishas) {
                let clip = this.audioClipMap.get(path)
                audioSource.clip = clip;
                audioSource.volume = 1
                if (loop) {
                    audioSource.loop = true;
                } else {
                    audioSource.loop = false;
                }
                audioSource.play()
                if (callback) {
                    callback(audioSource)
                }
            } else {
                ResourceMgr.getInstance().loadRes(bundle, String(path), AudioClip, (res: AudioClip) => {
                    audioSource.clip = res;
                    this.audioClipMap.set(path, res)

                    audioSource.volume = 1
                    if (loop) {
                        audioSource.loop = true;
                    } else {
                        audioSource.loop = false;
                    }
                    audioSource.play()
                    if (callback) {
                        callback(audioSource)
                    }
                })
            }
        }
    }
    public stopEffect() {
        let audioSource = this.getAudioSource("effect")
        if (audioSource) {
            audioSource.stop();
        }
    }

    private normalButtonAudio: AudioId;
    /**设置点击按钮的默认音效 */
    public setButtonNomalAudio(audioId: AudioId) {
        this.normalButtonAudio = audioId;
    }

    /**默认的点击音效 */
    public playAudioButtonClicked() {
        if (this.normalButtonAudio) {
            this.playEffect(this.normalButtonAudio)
        }
    }
}